const { autoUpdater } = require("electron-updater");
const { app, dialog, ipcMain } = require("electron");
const updateConfig = require("./update-config");
const fs = require("fs");
const path = require("path");

class Updater {
  constructor(mainWindow) {
    this.mainWindow = mainWindow;
    this.isUpdateAvailable = false;
    this.isUpdateDownloaded = false;
    this.retryCount = 0;
    this.maxRetries = updateConfig.errorHandling.maxRetries || 3;

    // 下载进度跟踪
    this.currentProgress = 0;
    this.currentSpeed = "0 KB/s";
    this.currentDownloaded = "0 B";
    this.currentTotal = "0 B";

    // 配置更新服务器URL
    if (
      updateConfig.updateServer.custom &&
      updateConfig.updateServer.custom.url
    ) {
      console.log(
        "设置自定义更新服务器:",
        updateConfig.updateServer.custom.url
      );
      autoUpdater.setFeedURL({
        provider: "generic",
        url: updateConfig.updateServer.custom.url,
        channel: "latest",
      });
    } else {
      console.log("使用默认更新服务器配置");
    }
    // 设置下载目录为应用安装目录
    let updateDir;
    if (updateConfig.strategy.downloadPath) {
      // 使用配置文件中的路径
      updateDir = updateConfig.strategy.downloadPath;
    } else {
      // 优先使用应用安装目录下的updates文件夹
      const appPath = app.getPath("exe");
      const appDir = path.dirname(appPath);
      updateDir = path.join(appDir, "updates");
    }
    // 确保更新目录存在
    try {
      if (!fs.existsSync(updateDir)) {
        fs.mkdirSync(updateDir, { recursive: true });
      }
    } catch (error) {
      console.warn(
        "无法在安装目录创建updates文件夹，使用用户数据目录:",
        error.message
      );
      // 备用方案：使用用户数据目录
      const userDataPath = app.getPath("userData");
      updateDir = path.join(userDataPath, "updates");
      if (!fs.existsSync(updateDir)) {
        fs.mkdirSync(updateDir, { recursive: true });
      }
    }
    // 设置下载目录
    autoUpdater.downloadPath = updateDir;
    console.log("更新下载目录设置为:", updateDir);
    // 使用配置文件中的设置
    autoUpdater.autoDownload = updateConfig.strategy.autoDownload;
    autoUpdater.autoInstallOnAppQuit = updateConfig.strategy.autoInstallOnQuit;
    autoUpdater.allowDowngrade = updateConfig.strategy.allowDowngrade;
    autoUpdater.allowPrerelease = updateConfig.strategy.allowPrerelease;
    autoUpdater.requestHeaders = updateConfig.strategy.requestHeaders;
    autoUpdater.timeout = updateConfig.strategy.timeout;

    this.setupEventHandlers();

    // 应用启动后延迟清理旧版本的下载文件
    this.scheduleCleanupAfterStartup();
  }

  setupEventHandlers() {
    // 检查更新错误
    autoUpdater.on("error", (err) => {
      console.error("更新检查错误详情:", {
        message: err.message,
        code: err.code,
        stack: err.stack,
        retryCount: this.retryCount,
      });
      // 检查是否为网络相关错误
      const isNetworkError = this.isNetworkError(err);
      if (isNetworkError && this.retryCount < this.maxRetries) {
        // 网络错误时进行重试
        this.retryUpdateCheck(err);
        return;
      }
      // 重置重试计数
      this.retryCount = 0;
      if (
        updateConfig.errorHandling.showErrorDialog &&
        !updateConfig.errorHandling.silentFail
      ) {
        const errorMessage = isNetworkError
          ? `网络连接超时，无法检查更新。请检查网络连接后重试。\n\n错误详情: ${err.message}`
          : `检查更新时发生错误: ${err.message}`;

        dialog.showErrorBox("更新错误", errorMessage);
      }

      // 关闭进度窗口（如果存在）
      this.closeProgressDialog();
    });
    // 检查更新中
    autoUpdater.on("checking-for-update", () => {
      console.log("正在检查更新... (重试次数:", this.retryCount, ")");
      // 只在主进程记录，不与渲染层通信
    });

    // 有可用更新
    autoUpdater.on("update-available", (info) => {
      console.log("发现可用更新:", info);
      this.isUpdateAvailable = true;
      this.retryCount = 0; // 重置重试计数
      // 检查是否为跳过的版本
      const userDataPath = app.getPath("userData");
      const skipFile = path.join(userDataPath, "skipped-updates.json");
      let skipped = [];
      try {
        if (fs.existsSync(skipFile)) {
          const content = fs.readFileSync(skipFile, "utf-8");
          skipped = JSON.parse(content);
        }
      } catch (e) {
        skipped = [];
      }
      if (skipped.includes(info.version)) {
        // 跳过该版本，不弹窗
        console.log("跳过版本:", info.version);
        return;
      }
      // 只在主进程显示更新对话框
      if (updateConfig.ui.showUpdateDialog) {
        this.showUpdateDialog(info);
      }
    });

    // 没有可用更新
    autoUpdater.on("update-not-available", (info) => {
      console.log("当前已是最新版本:", info);
      this.retryCount = 0; // 重置重试计数
    });

    // 下载进度
    autoUpdater.on("download-progress", (progressObj) => {
      // 格式化下载速度
      const speed = this.formatDownloadSpeed(progressObj.bytesPerSecond);
      const downloaded = this.formatFileSize(progressObj.transferred);
      const total = this.formatFileSize(progressObj.total);
      // 更新进度跟踪变量
      this.currentProgress = Math.round(progressObj.percent);
      this.currentSpeed = speed;
      this.currentDownloaded = downloaded;
      this.currentTotal = total;
      const progressInfo = {
        ...progressObj,
        speed: speed,
        downloaded: downloaded,
        total: total,
        percent: this.currentProgress,
        status: "downloading",
      };

      this.updateProgressDialog(progressInfo);
    });
    // 下载开始
    autoUpdater.on("download-started", () => {
      console.log("开始下载更新文件");
    });
    // 更新下载完成
    autoUpdater.on("update-downloaded", (info) => {
      console.log("更新下载完成:", info);
      this.isUpdateDownloaded = true;
      // 下载完成
      console.log("下载完成，准备安装更新...");
      // 关闭进度窗口
      this.closeProgressDialog();
      // 直接安装并重启，不显示对话框
      console.log("自动安装更新并重启应用");
      autoUpdater.quitAndInstall();
    });
    // 设置IPC监听器
    this.setupIpcHandlers();
  }

  // 判断是否为网络相关错误
  isNetworkError(err) {
    const networkErrorCodes = [
      "net::ERR_CONNECTION_TIMED_OUT",
      "net::ERR_CONNECTION_REFUSED",
      "net::ERR_NETWORK_CHANGED",
      "net::ERR_INTERNET_DISCONNECTED",
      "net::ERR_NAME_NOT_RESOLVED",
      "net::ERR_ADDRESS_UNREACHABLE",
      "ECONNREFUSED",
      "ENOTFOUND",
      "ETIMEDOUT",
      "ECONNRESET",
    ];

    return networkErrorCodes.some(
      (code) =>
        err.message.includes(code) ||
        (err.code && err.code.includes(code)) ||
        err.stack.includes(code)
    );
  }

  // 重试更新检查
  async retryUpdateCheck(originalError) {
    this.retryCount++;
    const retryDelay =
      updateConfig.errorHandling.retryDelay * Math.pow(2, this.retryCount - 1); // 指数退避
    console.log(`网络错误，${retryDelay}ms后进行第${this.retryCount}次重试...`);
    setTimeout(async () => {
      try {
        await autoUpdater.checkForUpdates();
      } catch (error) {
        console.error(`第${this.retryCount}次重试失败:`, error.message);
      }
    }, retryDelay);
  }

  setupIpcHandlers() {
    // 检查更新
    ipcMain.handle("check-for-updates", async () => {
      try {
        // 重置重试计数
        this.retryCount = 0;
        await autoUpdater.checkForUpdates();
        return { success: true };
      } catch (error) {
        console.error("手动检查更新失败:", error);
        const isNetworkError = this.isNetworkError(error);

        return {
          success: false,
          error: error.message,
          isNetworkError: isNetworkError,
          code: error.code,
          retryCount: this.retryCount,
        };
      }
    });

    // 下载更新
    ipcMain.handle("download-update", async () => {
      try {
        if (this.isUpdateAvailable) {
          await autoUpdater.downloadUpdate();
          return { success: true };
        } else {
          return { success: false, error: "没有可用的更新" };
        }
      } catch (error) {
        console.error("下载更新失败:", error);
        return { success: false, error: error.message };
      }
    });

    // 安装更新
    ipcMain.handle("install-update", async () => {
      try {
        if (this.isUpdateDownloaded) {
          autoUpdater.quitAndInstall();
          return { success: true };
        } else {
          return { success: false, error: "更新尚未下载完成" };
        }
      } catch (error) {
        console.error("安装更新失败:", error);
        return { success: false, error: error.message };
      }
    });

    // 获取更新状态
    ipcMain.handle("get-update-status", () => {
      return {
        isUpdateAvailable: this.isUpdateAvailable,
        isUpdateDownloaded: this.isUpdateDownloaded,
      };
    });

    // 获取配置信息
    ipcMain.handle("get-update-config", () => {
      return {
        currentVersion: updateConfig.version.current,
        minSupportedVersion: updateConfig.version.minSupported,
        forceUpdate: updateConfig.version.forceUpdate,
      };
    });

    // 获取下载路径信息
    ipcMain.handle("get-update-download-path", () => {
      const userDataPath = app.getPath("userData");
      const updateDir = path.join(userDataPath, "updates");
      return {
        downloadPath: autoUpdater.downloadPath || updateDir,
        userDataPath: userDataPath,
        appPath: app.getPath("exe"),
      };
    });

    // 获取更新服务器信息
    ipcMain.handle("get-update-server-info", () => {
      return {
        updateServer: updateConfig.updateServer,
        timeout: updateConfig.strategy.timeout,
        maxRetries: updateConfig.errorHandling.maxRetries,
        retryDelay: updateConfig.errorHandling.retryDelay,
        currentRetryCount: this.retryCount,
      };
    });

    // 获取当前下载进度
    ipcMain.handle("get-download-progress", () => {
      return {
        isDownloading: this.isUpdateAvailable && !this.isUpdateDownloaded,
        isDownloaded: this.isUpdateDownloaded,
        progress: this.currentProgress || 0,
        speed: this.currentSpeed || "0 KB/s",
        downloaded: this.currentDownloaded || "0 B",
        total: this.currentTotal || "0 B",
      };
    });

    // 手动清理下载文件
    ipcMain.handle("cleanup-downloaded-files", async () => {
      try {
        this.cleanupDownloadedFiles();
        return { success: true, message: "清理完成" };
      } catch (error) {
        console.error("手动清理失败:", error);
        return { success: false, error: error.message };
      }
    });

    // 获取下载目录文件信息
    ipcMain.handle("get-download-directory-info", () => {
      try {
        const downloadPath = autoUpdater.downloadPath;
        if (!downloadPath || !fs.existsSync(downloadPath)) {
          return {
            exists: false,
            path: downloadPath,
            files: [],
            message: "下载目录不存在",
          };
        }

        const files = fs.readdirSync(downloadPath);
        const fileInfo = files.map((file) => {
          const filePath = path.join(downloadPath, file);
          const stats = fs.statSync(filePath);
          return {
            name: file,
            path: filePath,
            size: stats.size,
            isFile: stats.isFile(),
            isDirectory: stats.isDirectory(),
            isUpdateFile: stats.isFile() ? this.isUpdateFile(file) : false,
            modifiedTime: stats.mtime,
          };
        });

        return {
          exists: true,
          path: downloadPath,
          files: fileInfo,
          totalFiles: fileInfo.length,
          updateFiles: fileInfo.filter((f) => f.isUpdateFile).length,
        };
      } catch (error) {
        console.error("获取下载目录信息失败:", error);
        return {
          exists: false,
          error: error.message,
        };
      }
    });
  }

  // 显示更新对话框
  async showUpdateDialog(info) {
    const buttons = ["立即下载"];
    if (updateConfig.ui.allowRemindLater) {
      buttons.push("稍后提醒");
    }
    if (updateConfig.ui.allowSkipVersion) {
      buttons.push("跳过此版本");
    }
    // 优先显示 releaseNotes/notes/description，没有则显示推荐更新
    let updateDetail = "";
    if (info.releaseNotes) {
      updateDetail =
        typeof info.releaseNotes === "string"
          ? info.releaseNotes
          : JSON.stringify(info.releaseNotes, null, 2);
    } else if (info.notes) {
      updateDetail = info.notes;
    } else if (info.description) {
      updateDetail = info.description;
    } else {
      updateDetail = "推荐更新";
    }

    const result = await dialog.showMessageBox(this.mainWindow, {
      type: "info",
      title: "发现新版本",
      message: `发现新版本 ${info.version}`,
      detail: `当前版本: ${app.getVersion()}\n新版本: ${
        info.version
      }\n\n${updateDetail}\n\n是否现在下载更新？`,
      buttons: buttons,
      defaultId: 0,
      cancelId: 1,
      timeout: updateConfig.ui.dialogTimeout,
    });

    switch (result.response) {
      case 0: // 立即下载
        this.downloadUpdate();
        break;
      case 1: // 稍后提醒
        if (updateConfig.ui.allowRemindLater) {
          this.scheduleReminder();
        }
        break;
      case 2: // 跳过此版本
        if (updateConfig.ui.allowSkipVersion) {
          this.skipVersion(info.version);
        }
        break;
    }
  }

  // 显示安装对话框
  async showInstallDialog(info) {
    const result = await dialog.showMessageBox(this.mainWindow, {
      type: "info",
      title: "更新下载完成",
      message: "更新已下载完成，需要重启应用以安装更新",
      detail: `新版本: ${info.version}\n\n重启后应用将自动安装更新。\n\n建议保存当前工作后重启。`,
      buttons: ["立即重启", "稍后重启"],
      defaultId: 0,
      cancelId: 1,
      timeout: updateConfig.ui.dialogTimeout,
    });

    if (result.response === 0) {
      // 立即重启
      console.log("用户选择立即重启");
      autoUpdater.quitAndInstall();
    } else {
      // 稍后重启
      console.log("用户选择稍后重启");
      console.log("安装已延迟");
    }
  }

  // 下载更新
  async downloadUpdate() {
    try {
      console.log("开始下载更新...");
      // 显示主进程下载进度对话框
      this.showMainProcessDownloadDialog();
      // 直接开始下载，不显示对话框
      await autoUpdater.downloadUpdate();
      console.log("下载更新完成");
    } catch (error) {
      console.error("下载更新失败:", error);
      if (updateConfig.errorHandling.showErrorDialog) {
        dialog.showErrorBox("下载失败", `下载更新时发生错误: ${error.message}`);
      }
    }
  }

  // 显示主进程下载进度对话框
  showMainProcessDownloadDialog() {
    // 通知渲染进程显示下载进度
    if (this.mainWindow && !this.mainWindow.isDestroyed()) {
      this.mainWindow.webContents.send("show-download-progress");
    }
  }

  // 更新下载进度对话框内容
  updateProgressDialog(progressInfo) {
    // 在控制台显示下载进度（可选，用于调试）
    console.log(`下载进度: ${progressInfo.percent}% - ${progressInfo.speed}`);
    // 通知渲染进程更新进度
    if (this.mainWindow && !this.mainWindow.isDestroyed()) {
      const progressData = {
        percent: progressInfo.percent,
        speed: progressInfo.speed,
        downloaded: progressInfo.downloaded,
        total: progressInfo.total,
      };
      this.mainWindow.webContents.send(
        "update-download-progress",
        progressData
      );
    }
  }

  // 关闭下载进度对话框
  closeProgressDialog() {
    // 通知渲染进程隐藏下载进度
    if (this.mainWindow && !this.mainWindow.isDestroyed()) {
      this.mainWindow.webContents.send("hide-download-progress");
    }
  }

  // 启动时检查更新
  checkForUpdatesOnStartup() {
    console.log("准备启动时检查更新...");
    console.log("当前配置:", {
      autoDownload: updateConfig.strategy.autoDownload,
      timeout: updateConfig.strategy.timeout,
      maxRetries: updateConfig.errorHandling.maxRetries,
      updateServer: updateConfig.updateServer,
    });

    // 使用配置文件中的延迟时间
    setTimeout(async () => {
      try {
        console.log("开始检查更新...");
        await autoUpdater.checkForUpdates();
      } catch (err) {
        console.error("启动时检查更新失败:", err);
        console.error("错误详情:", {
          message: err.message,
          code: err.code,
          stack: err.stack,
        });
        // 如果配置了静默失败，不抛出错误
        if (!updateConfig.errorHandling.silentFail) {
          throw err;
        }
      }
    }, updateConfig.startupDelay);
  }

  // 手动检查更新
  async checkForUpdates() {
    try {
      await autoUpdater.checkForUpdates();
    } catch (error) {
      console.error("检查更新失败:", error);
      throw error;
    }
  }

  // 安排稍后提醒
  scheduleReminder() {
    // 可以设置定时器，稍后再次提醒
    setTimeout(() => {
      if (this.isUpdateAvailable) {
        this.showUpdateDialog(this.updateInfo);
      }
    }, updateConfig.checkInterval);
  }

  // 跳过版本
  skipVersion(version) {
    // 记录跳过的版本到本地配置文件
    const userDataPath =
      this.mainWindow && this.mainWindow.app
        ? this.mainWindow.app.getPath("userData")
        : app
        ? app.getPath("userData")
        : "";
    const skipFile = path.join(userDataPath, "skipped-updates.json");
    let skipped = [];
    try {
      if (fs.existsSync(skipFile)) {
        const content = fs.readFileSync(skipFile, "utf-8");
        skipped = JSON.parse(content);
      }
    } catch (e) {
      skipped = [];
    }
    if (!skipped.includes(version)) {
      skipped.push(version);
      try {
        fs.writeFileSync(skipFile, JSON.stringify(skipped, null, 2), "utf-8");
      } catch (e) {
        console.error("写入跳过版本文件失败:", e);
      }
    }
    console.log("版本已跳过:", version);
  }

  // 格式化下载速度
  formatDownloadSpeed(bytesPerSecond) {
    const units = ["B/s", "KB/s", "MB/s", "GB/s"];
    let unitIndex = 0;
    let speed = bytesPerSecond;
    while (speed > 1024 && unitIndex < units.length - 1) {
      speed /= 1024;
      unitIndex++;
    }
    return `${speed.toFixed(2)} ${units[unitIndex]}`;
  }

  // 格式化文件大小
  formatFileSize(bytes) {
    const units = ["B", "KB", "MB", "GB"];
    let unitIndex = 0;
    let size = bytes;
    while (size > 1024 && unitIndex < units.length - 1) {
      size /= 1024;
      unitIndex++;
    }
    return `${size.toFixed(2)} ${units[unitIndex]}`;
  }

  // 清理下载的更新文件
  cleanupDownloadedFiles() {
    try {
      const downloadPath = autoUpdater.downloadPath;
      console.log("开始清理下载文件，路径:", downloadPath);
      if (!downloadPath || !fs.existsSync(downloadPath)) {
        console.log("下载路径不存在，跳过清理");
        return;
      }
      // 读取下载目录中的所有文件
      const files = fs.readdirSync(downloadPath);
      let cleanedCount = 0;
      files.forEach((file) => {
        const filePath = path.join(downloadPath, file);
        const stats = fs.statSync(filePath);
        // 检查是否为文件（不是目录）
        if (stats.isFile()) {
          // 检查是否为更新相关文件
          if (this.isUpdateFile(file)) {
            try {
              fs.unlinkSync(filePath);
              console.log("已删除更新文件:", file);
              cleanedCount++;
            } catch (error) {
              console.error("删除文件失败:", file, error.message);
            }
          }
        }
      });
      console.log(`清理完成，共删除 ${cleanedCount} 个更新文件`);
      // 尝试删除空的下载目录
      try {
        const remainingFiles = fs.readdirSync(downloadPath);
        if (remainingFiles.length === 0) {
          fs.rmdirSync(downloadPath);
          console.log("已删除空的下载目录:", downloadPath);
        }
      } catch (error) {
        console.log("删除下载目录失败（可能不为空）:", error.message);
      }
    } catch (error) {
      console.error("清理下载文件时发生错误:", error.message);
    }
  }

  // 判断是否为更新文件
  isUpdateFile(filename) {
    const updateFilePatterns = [
      /\.exe$/i, // Windows 可执行文件
      /\.dmg$/i, // macOS 安装包
      /\.deb$/i, // Debian 包
      /\.rpm$/i, // RPM 包
      /\.AppImage$/i, // AppImage 文件
      /latest\.yml$/i, // 更新清单文件
      /latest-mac\.yml$/i, // macOS 更新清单
      /latest-linux\.yml$/i, // Linux 更新清单
      /latest\.json$/i, // JSON 格式更新清单
      /\.blockmap$/i, // 增量更新文件
      /\.sig$/i, // 签名文件
      /update\.exe$/i, // 更新程序
      /updater\.exe$/i, // 更新器
      /项目管理系统.*\.exe$/i, // 项目管理系统安装包
      /project-management.*\.exe$/i, // 英文名称安装包
    ];

    return updateFilePatterns.some((pattern) => pattern.test(filename));
  }

  // 应用启动后延迟清理旧版本的下载文件
  scheduleCleanupAfterStartup() {
    // 延迟30秒后清理，确保应用完全启动
    setTimeout(() => {
      if (updateConfig.strategy.autoCleanupFiles) {
        console.log("应用启动后清理旧版本的下载文件...");
        this.cleanupDownloadedFiles();
      } else {
        console.log("自动清理功能已禁用，保留下载文件");
      }
    }, 30000); // 30秒延迟
  }
}

module.exports = Updater;
